/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the robot4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */

package com.hitqz.robot.daemon.quartz.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hitqz.robot.common.security.service.RobotUser;
import com.hitqz.robot.common.security.util.SecurityUtils;
import com.hitqz.robot.daemon.quartz.constants.RobotQuartzEnum;
import com.hitqz.robot.daemon.quartz.entity.SysJob;
import com.hitqz.robot.daemon.quartz.mapper.SysJobMapper;
import com.hitqz.robot.daemon.quartz.service.SysJobService;
import com.hitqz.robot.daemon.quartz.util.TaskUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.stereotype.Service;

import java.util.Optional;

/**
 * 定时任务调度表
 *
 * @author frwcloud
 * @date 2019-01-27 10:04:42
 */
@Slf4j
@Service
@AllArgsConstructor
public class SysJobServiceImpl extends ServiceImpl<SysJobMapper, SysJob> implements SysJobService {

    private final Scheduler scheduler;


    private final TaskUtil taskUtil;

    @Override
    public boolean startJob(Long id) throws SchedulerException {
        SysJob querySysJob = this.baseMapper.selectById(id);
        if (querySysJob == null) {
            return false;
        }
        // 如果定时任务不存在，强制状态为1已发布
        if (!scheduler.checkExists(TaskUtil.getJobKey(querySysJob))) {
            querySysJob.setJobStatus(RobotQuartzEnum.JOB_STATUS_RELEASE.getType());
            log.warn("定时任务不在quartz中,任务id:{},强制状态为已发布并加入调度器", id);
        }
        taskUtil.addOrUpateJob(querySysJob, scheduler);
        if (!RobotQuartzEnum.JOB_STATUS_RELEASE.getType().equals(querySysJob.getJobStatus())) {
            taskUtil.resumeJob(querySysJob, scheduler);
        }
        // 更新定时任务状态为运行状态2
        this.updateById(SysJob.builder().jobId(id).jobStatus(RobotQuartzEnum.JOB_STATUS_RUNNING.getType()).build());
        return true;
    }

    @Override
    public boolean pauseJob(Long id) throws SchedulerException {
        SysJob querySysJob = this.getById(id);
        // 更新定时任务状态条件，运行状态2更新为暂停状态3
        this.updateById(SysJob.builder()
                .jobId(querySysJob.getJobId())
                .jobStatus(RobotQuartzEnum.JOB_STATUS_NOT_RUNNING.getType())
                .build());
        taskUtil.pauseJob(querySysJob, scheduler);
        return true;
    }

    @Override
    public SysJob addJobByRobotJob(String name, String cron, String methodParams) {
        SysJob sysJob = new SysJob();
        sysJob.setJobName(name);
        sysJob.setCreateBy((Optional.ofNullable(SecurityUtils.getUser()).orElse(
                new RobotUser(1L, 1L, "otherUser",
                        "123456", "admin", true, true, true, true,
                        AuthorityUtils
                                .createAuthorityList())).getUsername()));
        sysJob.setClassName("robotJob");
        sysJob.setJobGroup("robotJob");
        sysJob.setJobType("2");
        sysJob.setJobExecuteStatus("0");
        sysJob.setMethodName("execute");
        sysJob.setCronExpression(cron);
        sysJob.setMethodParamsValue(methodParams);
        sysJob.setMisfirePolicy("3");
        sysJob.setJobTenantType("1");
        sysJob.setJobStatus(RobotQuartzEnum.JOB_STATUS_RELEASE.getType());
        this.save(sysJob);
        return sysJob;
    }

    @Override
    public boolean runOneJob(Long id) throws SchedulerException {
        SysJob querySysJob = this.getById(id);

        // 执行定时任务前判定任务是否在quartz中
        if (!scheduler.checkExists(TaskUtil.getJobKey(querySysJob))) {
            querySysJob.setJobStatus(RobotQuartzEnum.JOB_STATUS_NOT_RUNNING.getType());
            log.warn("立刻执行定时任务-定时任务不在quartz中,任务id:{},强制状态为暂停并加入调度器", id);
            taskUtil.addOrUpateJob(querySysJob, scheduler);
        }
        return TaskUtil.runOnce(scheduler, querySysJob);
    }
}
